fix(goal): explicit 模式下启动或恢复 Goal 后开放生命周期工具 (#464) - #491
Conversation
在 showLifecycleTools() 中单调加载 session 能力组,确保在 explicit 发现模式下创建或恢复 Goal 时,模型续跑能正常调用 get_goal 和 update_goal。 解决 openpi-dev#464
ab35f18 to
8bc79a0
Compare
tt-a1i
left a comment
There was a problem hiding this comment.
Reviewed at exact head 8bc79a0. The active-Goal fix is valuable and no P0/P1 was found, but I am not auto-merging this because it changes the model-visible lifecycle tool context.
Spec
[P2] restore() calls showLifecycleTools() for every visible persisted Goal snapshot before checking whether it is active or whether the user accepts resume. A completed Goal, or a paused/blocked Goal whose resume prompt is declined, therefore loads the entire session capability for later ordinary turns, exposing Goal lifecycle tools plus the grouped task entry tool even though no Goal was restored. This exceeds Issue #464’s active/resumed scope and the zero-resident acceptance for sessions where no Goal is created or restored. Please gate tool loading on active/accepted restoration and add completed-history plus declined-resume tests.
Standards
No hard violation found. Non-blocking P3: the real-Pi integration setup is repeated across four tests and would benefit from a fixture helper.
问题
默认
explicitcapability discovery 模式下,用户通过/goal <objective>创建 Goal、或恢复已有的 active Goal 后,Runtime 会启动续跑回合并提示模型在完成后调用update_goal。然而,由于goal归属于session能力组,ownerIsVisible(state, "goal")需要检查state.loaded.has("session")。在 explicit 模式下初始state.loaded为空,导致模型实际接收到的可用工具中缺少get_goal和update_goal,执行状态与可用工具脱节。Fixes #464价值
让用户明确启动或恢复的 Goal 能够正常查看进度、报告阻塞并顺利调用
update_goal完成收尾闭环,避免工作完成后陷入死循环继续空耗 Token/回合;同时保留普通新 Session 零常驻 OpenPI 模型工具的不变式。实现方案
extensions/goal/index.ts中,修改showLifecycleTools():在调用patchOwnedTools(pi, "goal", { enable: ... })之前先调用loadOpenPiCapabilities(pi, ["session"])。session能力组一旦加载即在当前 Session 内保持已加载,而get_goal/update_goal生命周期工具继续由 Goal controller 按状态动态启闭。/goal resume命令行以及 TUI 交互确认恢复路径中,在controller.kickoff(ctx)前显式调用showLifecycleTools(),确保恢复的目标同样能够解除工具门禁。tests/extensions/goal/index.test.ts中的extensionHarness,显式提供事件总线events: { on, emit },避免测试落入“缺少 events 则假定全部可见”的 fallback 逻辑;验证新 Session 初始工具仅为["read", "third_party_tool"]。tests/extensions/goal/goal-surface.integration.test.ts,使用真实createAgentSession覆盖:新会话/goal <objective>续跑与正常完成收尾、Session reload 恢复、Session fork 工具保留与延迟续跑、以及update_goal连续 3 回合 blocked 严格审计。验证
node --test --experimental-strip-types tests/extensions/goal/goal-surface.integration.test.ts:4/4 测试通过(真实 Pi 会话端到端续跑、reload、fork 与 blocked 审计)。node --test --experimental-strip-types tests/extensions/goal/index.test.ts:9/9 单元测试通过。node --test --experimental-strip-types tests/extensions/shared/tool-surface.integration.test.ts:7/7 集成测试通过。npx biome format tests/extensions/goal/ extensions/goal/:格式检查通过。npx biome lint tests/extensions/goal/ extensions/goal/ --error-on-warnings:无 lint 告警或错误。node scripts/check-config-contract.mjs:通过(15 个持久化字段契约检查)。node scripts/check-discipline-ledger.mjs:通过(12 行 Discipline Ledger 检查)。影响
get_goal和update_goal。未开启 Goal 的纯净会话依然保持零 OpenPI 常驻工具。session能力组;fork 继续遵守用户输入前延迟自动续跑的约定。